﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UFPE.CIn.Abc.Primality.Algorithms;
using UFPE.CIn.Abc.Primality.Util;
using System.IO;
using System.Diagnostics;

namespace ConsoleTester
{
    class Program
    {
        static void Main(string[] args)
        {
            
            //while (true)
            //{
            //    long value = -1;
            //    try
            //    {
            //        string typed = Console.ReadLine();

            //        value = Convert.ToInt64(typed);
            //    }
            //    catch
            //    {
            //        Console.WriteLine("Valor Inválido!");
            //        continue;
            //    }
            //    if (value == -1)
            //    {
            //        break;
            //    }

            //    Console.Write(value + " eh potencia perfeita? ");
            //    Console.WriteLine(AKS.IsPerfectPower(value));
            //}

            AKSL aksl = new AKSL();
            AKS aks = new AKS();
            Console.WriteLine("AKSL: " + aksl.calcularR(1000000007));
            Console.WriteLine("AKS: " + aks.calcularR(1000000007));

            //FileStream fs = new FileStream("valoresR.csv", FileMode.Create);
            //TextWriter tw = new StreamWriter(fs);
            //StringBuilder sb = new StringBuilder("i;aks_r\n");
            //for (int i = 1; i < 20000; i++)
            //{
            //    sb.AppendFormat("{0};{1}\n", i, AKS.Instance.calcularR(i));
            //}
            //tw.Write(sb.ToString());                                
            //tw.Close();
            //fs.Close();

            //FileStream fs = new FileStream("valoresR.csv", FileMode.Create);
            //TextWriter tw = new StreamWriter(fs);

            //StringBuilder sb = new StringBuilder("i;aks_r;aks_t;aksv6_r;aksv6_t");

            //Stopwatch sw = new Stopwatch();

            //foreach (var i in BigInteger.primesBelow1000000)
            //{
            //    //Console.WriteLine("i: " + i + " " + AKS.Instance.calcularR(i) + " " + AKSL.Instance.calcularR(i));	 
            //    sb.Append(i);
            //    sw.Start();
            //    long temp = AKS.Instance.calcularR(i);
            //    sw.Stop();
            //    sb.Append(String.Format(";{0};{1}", temp, sw.ElapsedMilliseconds));
            //    sw.Reset();
            //    sw.Start();
            //    temp = AKSL.Instance.calcularR(i);
            //    sw.Stop();
            //    sb.Append(String.Format(";{0};{1}\n", temp, sw.ElapsedMilliseconds));
            //    sw.Reset();

            //    if (i > 2000) break;
            //}

            //tw.Write(sb.ToString());

            //tw.Close();
            //fs.Close();


            //for (int i = 3; i < 11701; i++)
            //{
            //    bool aks = AKS.Instance.IsPrime(i);
            //    bool aksl = AKSL.Instance.IsPrime(i);
            //    bool td = TrialDivision.Instance.IsPrime(i);
            //    if ((aks != aksl) || (aks != td) || (aksl != td))
            //    {
            //        Console.WriteLine(String.Format("{0} diferente! AKS: {1}, AKSL: {2}, TD: {3}", i, aks, aksl, td));
            //    }
            //}

            //Console.WriteLine(BigInteger.primesBelow1000000.Length);

            //long[] res = AKS.Instance.Fatorar(3);

            //foreach (long item in res)
            //{
            //    Console.Write(item + ", ");
            //}

            //Console.WriteLine();

            //FileStream fs = new FileStream("primes.txt", FileMode.Create);
            //TextWriter tw = new StreamWriter(fs);

            //SieveOfEratosthenes.Instance.IsPrime(1000000, tw);

            //tw.Flush();
            //tw.Close();
            //fs.Close();

            //int[] lista = { 7, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 4194319, 8388617, 16777259 };

            //foreach (int item in lista)
            //{
            //    Console.WriteLine(item + " " + AKSL.Instance.IsPrime(item) + " em " + AKSL.Instance.TimeLastRun);
            //}

            //for (int i = 3; i < 100000; i++)
            //{
            //    bool isPrimeAKSL = AKSL.Instance.IsPrime(i);
            //    bool isPrimeTD = TrialDivision.Instance.IsPrime(i);

            //    if (isPrimeAKSL != isPrimeTD)
            //    {
            //        Console.WriteLine(i + " - " + isPrimeAKSL + " / " + isPrimeTD);
            //    }

            //    if (i % 1000 == 0)
            //    {
            //        Console.WriteLine(i);
            //    }
            //}

            //long[] lista = { 5, 37, 977, 2909, 11699, 11701, 86599, 123457, 2284423, 96447077, 484240567, 1307135101, 435465768733, 3435465768991, 65434218790277, 700000000000051, 7000000000000037, 10000000000000061, 100000000000000003 };
            /*long[] lista = { 7, 17, 125, 149, 2547, 3137, 10133, 32561, 160583, 268069, 1771561, 2969023, 7741009, 9786539, 12434839, 86457079, 100982933, 879673117, 2492813497 };
            foreach (long item in lista)
            {
                Console.WriteLine(item + " " + AKS.Instance.calcularR(item));
            }*/

            //Console.WriteLine(aks.IsPerfectPower(197798515015396));

            while (true)
            {
                Console.WriteLine("Digite o número a ser testado: (Digite 1 para sair)");
                BigInteger value = -1;
                try
                {
                    string typed = Console.ReadLine();

                    value = new BigInteger(typed, 10); 
                }
                catch
                {
                    Console.WriteLine("Valor Inválido!");
                    continue;
                }
                if (value == 1)
                {
                    break;
                }

                
                Console.WriteLine("Testando " + value + "...");
                bool isPrime;

                //  ***** TESTE DivisaoPorTentativa *****
                isPrime = TrialDivision.Instance.IsPrime(value);
                Console.WriteLine("Eh primo? " + isPrime);
                if (!isPrime)
                {
                    Console.WriteLine("Menor divisor maior que 1 eh " + TrialDivision.Instance.Factor);
                }
                Console.WriteLine(String.Format("O teste levou {0} ms\n", TrialDivision.Instance.TimeLastRun));

                //  ***** TESTE Solovay-Strassen *****
                //bool isPrime = SolovayStrassen.Instance.IsProbablyPrime(value, 50);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", SolovayStrassen.Instance.TimeLastRun));

                //  ***** TESTE Miller-Rabin *****
                //bool isPrime = MillerRabin.Instance.IsPrime(value, 25);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", MillerRabin.Instance.TimeLastRun));

                //  ***** TESTE Fermat *****
                //isPrime = FermatPrimalityTest.Instance.IsPrime(value, 20);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", FermatPrimalityTest.Instance.TimeLastRun));

                //  ***** TESTE LucasSelfridge *****
                //isPrime = LucasSelfridge.Instance.IsPrime(value);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", LucasSelfridge.Instance.TimeLastRun));

                //  ***** TESTE Baillie-PSW *****
                //isPrime = BailliePSW.Instance.IsPrime(value, true);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", BailliePSW.Instance.TimeLastRun));

                //  ***** TESTE AKS *****
                //isPrime = AKS.Instance.IsPrime(value, true);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", AKS.Instance.TimeLastRun));

                //  ***** TESTE AKSL *****
                //isPrime = AKSL.Instance.IsPrime(value, true);
                //Console.WriteLine("Eh primo? " + isPrime);
                //Console.WriteLine(String.Format("O teste levou {0} ms\n", AKSL.Instance.TimeLastRun));
            }
        }
    }
}
